/**
 *	Wrapper for AIR's network functions.
 *  @author Juntalis
 */

/**
 * Wrapper for the TCP Socket
 * Make sure to call socket.init() or else it wont work.
 */
function socket() {
	/**
	 * Whether or not our socket is initialized.
	 */
	var _blInit = false;
	/* Callbacks */
	var _cbConnHandle = null;
	var _cbCloseHandle = null;
	var _cbRecvHandle = null;
	var _cbIOErrHandle = null;
	var _cbSecHandle = null;
	
	/**
	 * Returns a socket's connection status.
	 * @return {Boolean}
	 */
	this.connected = function() {
		if (this.objSocket != null) {
			return this.objSocket.connected;
		} else {
			this.init();
			return false;
		}
	}
	
	/**
	 * Assign a handler for connection.
	 * @param {Function} cb	Needs to be function(event).
	 */
	this.handleConnection = function(cb) {
		if(cb) _cbConnHandle = cb;
	}
	
	/**
	 * Assign a handler for disconnection.
	 * @param {Function} cb	Needs to be function(event).
	 */
	this.handleClose = function(cb) {
		if(cb) _cbCloseHandle = cb;
	}
	
	/**
	 * Assign a handler for data receiving.
	 * @param {Function} cb	Needs to be function(event).
	 */
	this.handleReceives = function(cb) {
		if(cb) _cbRecvHandle = cb;
	}
	
	/**
	 * Assign a handler for IO errors.
	 * @param {Function} cb	Needs to be function(event).
	 */
	this.handleIOErrors = function(cb) {
		if(cb) _cbIOErrHandle = cb;
	}
	
	/**
	 * Assign a handler for security errors.
	 * @param {Function} cb	Needs to be function(event).
	 */
	this.handleSecErrors = function(cb) {
		if(cb) _cbSecErrHandle = cb;
	}
		
	/**
	 * The actual AIR socket being used.
	 */
	this.objSocket = null;
	
	/**
	 * Proxy to AIR socket's connect.
	 */
	this.connect;
	
	/**
	 * Proxy to AIR socket's close.
	 */
	this.close;
	
	/**
	 * Proxy to AIR socket's close.
	 */
	this.disconnect;
	
	/**
	 * Sends msg to the server. Automatically checks for a \n character at the end of the message. If none, it adds one.
	 * @param {Object} msg String to send to the server.
	 */
	this.send = function(msg) {
        if(!msg) return;
		if (msg.charAt(msg.length - 1) != "\n") msg += "\n";
		
        try {
            this.objSocket.writeUTFBytes(msg);
			this.objSocket.flush();
        } catch(err) {
            if (_TRACE.SOCKET) trace(err);
        }
		if (_DEBUG.SOCKET)
			console.log("Sent: " + msg);
    };
	
	/**
	 * Receives all available bytes from our socket.
	 * @return {String}
	 */
	this.recv = function() {
		try {
			var strData = this.objSocket.readUTFBytes( this.objSocket.bytesAvailable );
		} catch(err) {
            if (_TRACE.SOCKET) trace(err);
        }
		if ((_DEBUG.SOCKET)&&(strData))
			$.each(strData.split("\n"),function(index,value){ if(value.length) console.log("Received: " + value); });
		return strData;
	};
	
	/**
	 * Socket Connection Handler
	 * @param {Object} event
	 */
	function _onConnect(event)
	{
		if (_TRACE.SOCKET) trace("ConnectHandler: " + event);
		if (_DEBUG.SOCKET) console.log("Socket Connected");
		if (_cbConnHandle) _cbConnHandle(event);
	};

	/**
	 * Socket Disconnection Handler
	 * @param {Object} event
	 */
	function _onClose(event)
	{
		if (_TRACE.SOCKET) trace("CloseHandler: " + event);
		if (_DEBUG.SOCKET) console.log("Disconnected.");
		if (_cbCloseHandle) _cbCloseHandle(event);
	};
		
	/**
	 * Receive Handler
	 * @param {Object} event
	 */
	function _onReceive(event)
	{
		 if (_TRACE.SOCKET) trace("ReceiveHandler: " + event);
		 if (_cbRecvHandle) _cbRecvHandle(event);
	}
	
	/**
	 * Input/Output Error Handler
	 * @param {Object} event
	 */
	function _onIOError(event)
	{
		if (_TRACE.SOCKET) trace("IOErrorHandler: " + event);
		if (_cbIOErrHandle) _cbIOErrHandle(event);
	}
	
	/**
	 * Security Error Handler
	 * @param {Object} event
	 */
	function _onSecurityError(event)
	{
		if (_TRACE.SOCKET) trace("SecurityErrorHandler: " + event);
		if (_cbSecErrHandle) _cbSecErrvHandle(event);
	}
		
	/**
	 * Initializes the socket.
	 */
	this.init = function()
	{
		if(_blInit) return;
		this.objSocket = new air.Socket();
		this.objSocket.addEventListener(air.Event.CLOSE, _onClose);
    	this.objSocket.addEventListener(air.Event.CONNECT, _onConnect);
    	this.objSocket.addEventListener(air.IOErrorEvent.IO_ERROR, _onIOError);
    	this.objSocket.addEventListener(air.SecurityErrorEvent.SECURITY_ERROR, _onSecurityError);
    	this.objSocket.addEventListener(air.ProgressEvent.SOCKET_DATA, _onReceive);
		this.connect = this.objSocket.connect;
		this.close = this.objSocket.close;
		this.disconnect = this.objSocket.close;
		_blInit = true;
	}
	
}
